home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-05-19 | 41.8 KB | 1,519 lines |
- Newsgroups: comp.sources.misc
- From: tony@ajfcal.UUCP (Tony Field)
- subject: v12i109: psf2.0 source 6/6
- Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
-
- Posting-number: Volume 12, Issue 109
- Submitted-by: tony@ajfcal.UUCP (Tony Field)
- Archive-name: psf2/part06
-
- psf2.0 source 6/6
- =================
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 6 (of 6)."
- # Contents: psf.c
- # Wrapped by ajf@trifid on Tue May 15 01:10:54 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'psf.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'psf.c'\"
- else
- echo shar: Extracting \"'psf.c'\" \(39736 characters\)
- sed "s/^X//" >'psf.c' <<'END_OF_FILE'
- X/* ta=4 */
- X/****************************************************************************
- X* p s f . c v2.0 *
- X* *
- X* Postscript filter *
- X* *
- X* Print text files to postscript printer. Allow 1-up, 2-up and 4-up *
- X* pages. Provisions are made to allow font selection by imbedded *
- X* escape sequences - to allow printing of man pages. The escape sequence *
- X* generated by "pnf" and "pmf" are compatible with psf. *
- X* *
- X* Copyright: 1989-Feb, Tony Field. tony@ajfcal *
- X* *
- X* The orginal underline algorithm (/showunderline) was provided by *
- X* Anders Thulin mcvax!helios!ath@uunet.uucp *
- X****************************************************************************/
- X
- X/* NOTE: tabstop=4 */
- X
- X/* Note: if you want psf to ignore any text that is already in postscript
- X format, then possibly modify function "process_file()" to
- X do the detection and copy the input file to stdout.
- X
- X I haven't checked this out in detail, but it looks reasonable.
- X Maybe a command line option should be used to enable/disable
- X detection of postscript text (it is nice to be able to print
- X out postscript code)?
- X*/
- X
- X/* NOTES: re: -d option: double sided print.
- X
- X Double sided print requires two scans over the data. The first
- X scan generates postscript output in normal (non-double sided) form.
- X A second scan examines the postscript and re-orders the output
- X to the printer. The second pass is always done by the "psd" filter.
- X
- X Psf generates extra information to make it easy for psd to work.
- X It simply constructs pointers to each of the %%Page: beginning
- X in the print file. (see function terminate_printer()) Psd
- X uses the pointers to "skip about" the file while it does the
- X actual page layout.
- X
- X If the target printer has two paper hoppers (i.e. #define HOPPER is
- X defined and "nslots > 2") then psf creates a temp file and system("psd
- X fname") is called to immediately generate the double sided output.
- X The user does not have to manually invoke psd.
- X
- X If HOPPER is not defined or nslots <= 1, psf simply creates an
- X appropriate output file and the user must manually invoke psd to
- X print the file.
- X
- X Double sided print is forced into this routine. It would have been
- X simple except for the fact that 2-up "book" format is supported.
- X The excuse for this strategy is, of course, to minimize the amount
- X of file processing overhead when double sided printing is done.
- X
- X If the double sided printing is for 8.5x5.5 inch paper printed
- X two-up, then psf carefully forgets (in function set_frame())
- X to put in page scale, rotation, and translation information.
- X The psd filter reads the page layout and carefully re-inserts
- X these when appropriate. If 2-up "books" are made, each logical
- X page becomes a separate page on the output temp file.
- X*/
- X
- X#include <stdio.h>
- X#include <math.h>
- X#include <time.h>
- X#include "patchlevel.h"
- X#include "psf.h"
- X
- X/* BINDIR is used to locate double sided printer "psd".
- X psd is called in function output_book ()
- X You may wish to remove the reference to "BINDIR" in output_book().
- X*/
- X
- X#ifndef BINDIR
- X#define BINDIR "\0"
- X#endif
- X
- X/* set up the mechanism for underline display */
- X
- X#ifndef FONTINFO
- X#define SHOWU(fp,ps) fprintf (fp, ") %d showuline\n", ps)
- X#else
- X#define SHOWU(fp,ps) fputs (") showunderline\n", fp)
- X#endif
- X
- X#define MAX_PAGES 500 /* max pages in a book */
- X#define LONG_STR 1000 /* long buffer line */
- X
- X#define min(x,y) ((x) < (y) ? (x) : (y))
- X#define max(x,y) ((x) > (y) ? (x) : (y))
- X
- X/* default font with and height - assumes Courier fixed pitch */
- X
- X#define NOMINAL_CWIDE 7.2 /* point width for Courier 12-point */
- X#define NOMINAL_POINTS 12 /* standard 12-point for printing */
- X
- X#define NORMAL 0x00 /* bitset for print_attributes */
- X#define ITALICS 0x01
- X#define BOLD 0x02
- X#define UNDERLINE 0x04 /* must be 0x04. underline is not a font */
- X
- X/* Paper physical dimensions. Each paper size supported must be described.
- X If the paper print areas specified are incorrect, you must modify them.
- X The default paper sizes are coded into psf and are set for a NEC LC890
- X printer. These defaults are overridden in the "psfprint.def" printer
- X definition file.
- X
- X All text work must preserve the physical margins and scale the
- X drawing area to reflect the 1-up, 2-up or 4-up magnification.
- X
- X
- X "paper_name" is the name used on the command line with the -g option
- X to select the paper size: eg -g legal
- X
- X "paper_tray" is the command that is necessary to select the
- X specified paper size. For example, if the "legal" sized paper is in
- X the "alternate print tray", the postscript commands necessary to
- X switch paper tray and to select the legal size must be specified in
- X the "paper_tray" structure element.
- X*/
- X
- Xtypedef struct /* measurement in point */
- X{ char paper_name[60]; /* name of paper size (for command line) */
- X char paper_tray[200]; /* postscript operator to select this tray */
- X int width; /* portrait point width of paper */
- X int height; /* portrait point height of paper */
- X int lx, ly, ux, uy;
- X int left_marg; /* margin widths (unprintable area) */
- X int bot_marg; /* " */
- X int right_marg; /* " */
- X int top_marg; /* " */
- X int x_size; /* generated by psf. */
- X int y_size; /* size after correction for line count */
- X int n_lines; /* " */
- X int n_chars; /* " */
- X} measure;
- X
- Xmeasure *p; /* working set of parameters (points to something below) */
- X
- X /* standard paper sizes in portrait layout (NEC LC890) */
- X /* These are defaults and are overridden in psfprint.def. */
- X
- Xmeasure page_types[30] =
- X{ { "letter",
- X "statusdict begin lettertray end",
- X 612, 792, 18, 15, 593, 777
- X },
- X { "legal",
- X "statusdict begin legaltray end",
- X 612, 1008, 18, 15, 593, 993
- X },
- X { "a4",
- X "statusdict begin a4tray end",
- X 595, 842, 18, 15, 578, 827
- X },
- X { "b5",
- X "statusdict begin b5tray end",
- X 516, 729, 18, 15, 497, 712
- X },
- X { "", /* end of paper list */
- X "",
- X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- X }
- X};
- X
- Xchar slots[4][100] =
- X{ "statusdict begin 1 setpapertray end",
- X "statusdict begin 2 setpapertray end",
- X "",
- X ""
- X} ;
- Xint nslots = 2;
- X
- X
- X/* Current information about page. Where are we, etc.
- X*/
- X
- Xint y_top_offset; /* offsets for each frame */
- Xint x_left_offset;
- Xint dx_home[4]; /* page frame home (0,0) translations */
- Xint dy_home[4];
- X
- Xint x,y; /* current x,y coordinate */
- Xdouble scale_x, scale_y; /* scale factors for 2-up, 4-up printing */
- Xint real_width;
- X
- Xlong *pg_loc; /* double side print byte ptr to %%Page: */
- Xint npg_loc; /* number of elements in pg_loc[] */
- X
- Xint book = 0; /* book format: double sided */
- Xint bookwork = 0; /* book format, 2-up print */
- Xint lines_on_page = 60; /* user print lines on page */
- Xint lines_total = 0; /* total number of lines for scale purposes */
- Xint chars_on_line = 80; /* default number of chars on line */
- Xint landscape = 0; /* 1 = landscape, 0 = portrait layout */
- Xint header = 0; /* 1 = print header at top of each page */
- Xint cross = 0; /* 1 = print cross on 4-up pages */
- Xint line_number = 0; /* current logical line number on page */
- Xint tab_size = 8; /* space translation for tabs. */
- Xint font_number = 0; /* one of the valid fonts in the printer */
- Xint point_size = 12; /* can be changed with the -p option */
- Xint x_user_offset = 0; /* offsets specified buy user */
- Xint y_user_offset = 0; /* points from physical page edge. */
- Xint set_paper_tray = 0; /* user has set paper tray selection */
- Xint set_line_count = 0; /* print line count on page */
- Xint set_total_count = 0; /* total line count on page */
- Xint set_point_size = 0; /* point size */
- Xint set_char_count = 0; /* characters on a line */
- Xint set_paper_bin = 0; /* paper bin (not page size) */
- Xchar header_text[100]; /* header line text */
- X
- Xint print_attribute = 0; /* such as BOLD, UNDERLINE, ITALICS */
- Xint default_font_number; /* set with -f option, or 0 */
- Xint default_point_size; /* assumes value due to -p option */
- Xint y_coord = 0; /* current logical page y-coordinate, points*/
- Xint x_coord = 0; /* current logical page x-coordinate, points*/
- Xint page_number; /* current page number for this file */
- Xint physical_page = 0; /* postscript physical page for multi-up */
- X
- X
- Xchar fname[100];
- Xchar now[50]; /* time of day for page headers */
- X
- X
- X/* to select a font, use 4 * font_number + print_attribute as index.
- X e.g. If font_number = 1 for Helvetica,
- X and print_attribute = 0x02 for BOLD
- X
- X then the actual font selected is fonts[4 * 1 + 2]
- X = Helvetica-Bold
- X
- X The various print attributes can be OR'ed together:
- X fonts [4 * 1 + ITALICS | BOLD]
- X
- X The following are default fonts - and are overridden in psfprint.def.
- X*/
- X
- X#define NFONTS 40 /* 4 variations * 9 font families */
- Xchar *fonts[NFONTS] =
- X{
- X "Courier", "Courier-Oblique", "Courier-Bold", "Courier-BoldOblique",
- X "Helvetica", "Helvetica-Oblique", "Helvetica-Bold", "Helvetica-BoldOblique",
- X "Times-Roman", "Times-Italic", "Times-Bold", "Times-BoldItalic",
- X "AvantGarde-Book", "AvantGarde-BookOblique", "AvantGarde-Demi", "AvantGarde-DemiOblique",
- X "Bookman-Light", "Bookman-LightItalic", "Bookman-Demi", "Bookman-DemiItalic",
- X "NewCenturySchlbk-Roman", "NewCenturySchlbk-Italic", "NewCenturySchlbk-Bold", "NewCenturySchlbk-BoldItalic",
- X "Palatino-Roman", "Palatino-Italic", "Palatino-Bold", "Palatino-BoldItalic",
- X "Helvetica-Narrow", "Helvetica-Narrow-Oblique", "Helvetica-Narrow-Bold", "Helvetica-Narrow-BoldOblique",
- X "Garamond-Light", "Garamond-LightItalic", "Garamond-Bold", "Garamond-BoldItalic",
- X "ZapfChancery-MediumItalic","ZapfChancery-MediumItalic","ZapfChancery-MediumItalic","ZapfChancery-MediumItalic"
- X} ;
- X
- Xint fonts_used[NFONTS];
- Xint fonts_have[NFONTS];
- X
- Xint max_frame = 1; /* max number of frames in use */
- Xint frame = -1; /* current frame in use */
- X
- XFILE *input_fp, *output_fp;
- X
- X/* input line and input line pointer */
- Xunsigned char *c;
- Xunsigned char line[LONG_STR + 1];
- X
- Xchar *pgmname;
- X
- Xchar *malloc();
- X
- Xmain (argc, argv)
- Xint argc;
- Xchar *argv[];
- X{ int c, i, j;
- X extern char *optarg;
- X extern int optind;
- X FILE *pdef;
- X
- X /* see if there is a psfprint.def printer definition file. If so,
- X use those parameters, rather than the hard-coded defaults.
- X */
- X
- X if ((pdef = fopen (PDEF, "r")) != NULL)
- X { nslots = 0;
- X fgets (line, 100, pdef);
- X for (i = 0; i < 28; i++)
- X { if (fgets (page_types[i].paper_name, 59, pdef) == NULL)
- X break;
- X trim (page_types[i].paper_name);
- X if (strncmp (page_types[i].paper_name, "*fonts", 6) == 0)
- X {
- X for (j = 0; j < NFONTS; j++)
- X fonts_have[j] = 0;
- X page_types[i].paper_name[0] = '\0';
- X while (fgets (line, 90, pdef) != NULL)
- X { trim (line);
- X if (*line == '*')
- X break;
- X for (j = 0; j < NFONTS; j++)
- X { if (comp (fonts[j], line) == 0)
- X { fonts_have[j] = 1;
- X break;
- X }
- X }
- X }
- X if (strncmp (line, "*slots", 6) == 0)
- X { while (fgets (line, 90, pdef) != NULL)
- X { trim (line);
- X if (strncmp (line, "*eof", 4) == 0)
- X break;
- X if (*line)
- X {
- X strcpy (slots[nslots], line);
- X if (++nslots > 3)
- X break;
- X }
- X }
- X }
- X break; /* end of file */
- X }
- X if (fgets (page_types[i].paper_tray, 199, pdef) == NULL)
- X bad_file();
- X trim (page_types[i].paper_tray);
- X if (fgets (line, 100, pdef) == NULL)
- X bad_file();
- X trim (line);
- X sscanf (line, "%d%d%d%d%d%d",
- X &page_types[i].width,
- X &page_types[i].height,
- X &page_types[i].lx,
- X &page_types[i].ly,
- X &page_types[i].ux,
- X &page_types[i].uy);
- X
- X }
- X page_types[i].paper_name[0] = '\0';
- X fclose (pdef);
- X }
- X else
- X { for (i = 0; i < NFONTS; i++)
- X fonts_have[i] = 1;
- X fonts_have[8] = 0;
- X }
- X
- X for (i = 0; page_types[i].paper_name[0]; i++)
- X { page_types[i].left_marg = page_types[i].lx;
- X page_types[i].bot_marg = page_types[i].ly;
- X page_types[i].top_marg = (page_types[i].height - 1) - page_types[i].uy;
- X page_types[i].right_marg = (page_types[i].width - 1) - page_types[i].ux;
- X
- X page_types[i].x_size = page_types[i].ux - page_types[i].lx + 1;
- X page_types[i].y_size = page_types[i].uy - page_types[i].ly + 1;
- X }
- X
- X pgmname = argv[0];
- X p = &page_types[0]; /* default to letter size paper */
- X *header_text = '\0';
- X scale_x = 1.0;
- X scale_y = 1.0;
- X if (strcmp (argv[1], "-") == 0 || strcmp (argv[1], "--") == 0)
- X usage();
- X while ((c = getopt(argc, argv, "124xhnwdi:m:b:c:g:H:l:L:f:t:p:-?")) != -1)
- X { switch (c)
- X {
- X case '1':
- X max_frame = 1;
- X scale_x = 1.0;
- X scale_y = 1.0;
- X break;
- X
- X case '2':
- X landscape = 1;
- X max_frame = 2;
- X scale_x = 0.647;
- X scale_y = 0.772;
- X break;
- X
- X case '4':
- X max_frame = 4;
- X scale_x = 0.5;
- X scale_y = 0.5;
- X break;
- X
- X case 'b':
- X if ((set_paper_bin = atoi (optarg)) > nslots)
- X { if (nslots = 0)
- X fprintf (stderr, "%s: no alternate bins permitted for this printer\n", nslots);
- X else
- X fprintf (stderr, "%s: paper bin greater than %d\n", pgmname, nslots);
- X exit (1);
- X }
- X break;
- X
- X case 'c':
- X chars_on_line = atoi (optarg);
- X set_char_count = 1;
- X break;
- X
- X case 'd':
- X book = 1;
- X break;
- X
- X case 'f':
- X if (*optarg > '9')
- X { for (i = 0; i < NFONTS; i += 4)
- X { if (compare (optarg, fonts[i]) == 0)
- X { font_number = i / 4;
- X break;
- X }
- X }
- X if (i >= NFONTS)
- X font_number = 0;
- X }
- X else
- X {
- X font_number = atoi (optarg);
- X if (font_number > (NFONTS / 4))
- X font_number = 0;
- X }
- X break;
- X
- X case 'g':
- X p = NULL;
- X for (i = 0; page_types[i].paper_name[0]; i++)
- X { if (compare (optarg, page_types[i].paper_name) == 0)
- X { p = &page_types[i];
- X break;
- X }
- X }
- X if (p == NULL)
- X usage ();
- X set_paper_tray = 1;
- X break;
- X
- X case 'l':
- X lines_on_page = atoi (optarg);
- X set_line_count = 1;
- X break;
- X
- X case 'L':
- X lines_total = atoi (optarg);
- X set_total_count = 1;
- X break;
- X
- X case 'h':
- X header = 1;
- X break;
- X
- X case 'H':
- X header = 2;
- X strcpy (header_text, optarg);
- X break;
- X
- X case 'i':
- X x_user_offset = atoi (optarg);
- X break;
- X
- X case 'm':
- X y_user_offset = atoi (optarg);
- X break;
- X
- X case 'n':
- X landscape = 0;
- X break;
- X
- X case 'p':
- X point_size = atoi (optarg);
- X set_point_size = 1;
- X break;
- X
- X case 't':
- X tab_size = atoi (optarg);
- X break;
- X
- X case 'w':
- X landscape = 1;
- X break;
- X
- X case 'x':
- X cross = 1;
- X break;
- X
- X default: usage ();
- X break;
- X }
- X }
- X
- X if (font_number * 4 > NFONTS)
- X { fprintf (stderr,"Font number invalid....\n");
- X usage ();
- X }
- X
- X if (header)
- X lines_on_page += 2;
- X
- X#ifdef HOPPER
- X if (book && nslots > 1)
- X {
- X if ((output_fp = fopen ("1psbook2.d34", "w")) == NULL)
- X { fprintf (stderr, "%s: cannot create work file\n", pgmname);
- X exit (1);
- X }
- X }
- X else
- X#endif
- X output_fp = stdout;
- X
- X if (book)
- X { if ((pg_loc = (long *) malloc (sizeof (long) * MAX_PAGES)) == NULL)
- X { fprintf (stderr, "%s: cannot allocate enough memory\n", pgmname);
- X exit (1);
- X }
- X npg_loc = 0;
- X }
- X
- X for (i = 0; i < NFONTS; i++)
- X fonts_used[i] = 0;
- X
- X page_number = -1;
- X line_number = 32000;
- X default_point_size = point_size;
- X default_font_number = font_number;
- X bookwork = book && landscape && (max_frame == 2);
- X *fname = 0;
- X
- X get_time (now);
- X scale_factors ();
- X prologue (output_fp);
- X if (optind >= argc)
- X { if (header == 1)
- X header = 0;
- X start_file ();
- X input_fp = stdin;
- X process_file ();
- X terminate_file ();
- X }
- X else for ( ; optind < argc; optind++)
- X { i = strlen (argv[optind]);
- X if (i > 38)
- X i -= 38;
- X else
- X i = 0;
- X strcpy (fname, argv[optind] + i);
- X if ((input_fp = fopen (argv[optind], "r")) == NULL)
- X { fprintf (stderr, "Unknown file: %s\n", argv[optind]);
- X continue;
- X }
- X start_file ();
- X process_file ();
- X terminate_file ();
- X fclose (input_fp);
- X }
- X terminate_printer ();
- X
- X if (book)
- X output_book ();
- X
- X exit (0);
- X}
- X
- X/****************************************************************************
- X* scale_factors () *
- X* Compute the x and y scale factors. If the print is for landscape, *
- X* adjust the paper size matrix (p->...) to reflect landscape rather *
- X* than portrait. *
- X****************************************************************************/
- X
- X/* scale factors are calculated from:
- X
- X unprintable size + scale factor * print size = total paper size
- X
- X total paper size - unprintable size
- X scale factor = --------------------------------------
- X print size
- X*/
- X
- Xscale_factors ()
- X{ int wide; /* width needed for char count */
- X int high; /* points needed for line count */
- X int i;
- X double char_width, scale;
- X
- X /* determine default number of characters and lines based upon
- X Courier 12 point, 10 pitch font, portrait layout
- X */
- X
- X char_width = NOMINAL_CWIDE; /* in points */
- X real_width = p->width; /* for initial axis translate only */
- X
- X p->n_chars = ceil ((double) p->x_size / NOMINAL_CWIDE);
- X p->n_lines = p->y_size / NOMINAL_POINTS;
- X
- X /* set line count relative to portrait measure */
- X
- X if (set_total_count == 0)
- X lines_total = p->n_lines;
- X
- X if (set_line_count == 0)
- X lines_on_page = p->n_lines;
- X
- X if (lines_total < lines_on_page)
- X { if (set_total_count)
- X lines_on_page = lines_total;
- X else
- X lines_total = lines_on_page;
- X }
- X
- X /* if landscape, then switch the height and width dimensions */
- X
- X if (landscape)
- X {
- X i = p->height; p->height = p->width; p->width = i;
- X i = p->left_marg; p->left_marg = p->bot_marg; p->bot_marg = i;
- X i = p->top_marg; p->top_marg = p->right_marg; p->right_marg = i;
- X i = p->lx; p->lx = p->ly; p->ly = i;
- X i = p->ux; p->ux = p->uy; p->uy = i;
- X i = p->x_size; p->x_size = p->y_size; p->y_size = i;
- X
- X if (max_frame == 1)
- X { scale = (double) p->y_size / (double) p->x_size;
- X p->n_chars = ceil ((double) p->n_chars * scale * scale);
- X }
- X }
- X if (set_char_count == 0)
- X chars_on_line = p->n_chars;
- X
- X if (set_point_size)
- X { scale = (double) point_size / (double) NOMINAL_POINTS;
- X lines_total = p->y_size / point_size;
- X if (set_char_count == 0)
- X { chars_on_line /= scale;
- X char_width *= scale;
- X }
- X }
- X else if (set_line_count || set_total_count)
- X {
- X if (set_char_count == 0)
- X { scale = (double) lines_total / (double) p->n_lines;
- X chars_on_line = ceil ((double) chars_on_line * scale);
- X }
- X }
- X
- X /* Ideally, we wish to use a decender value of 0.5 line.
- X This is yieds a scale factor of 1.0 for Courier in default
- X portrait mode. Hopefully, this is not a problem with
- X other fonts.
- X */
- X high = ceil ((double) point_size * ((double) lines_total + 0.51));
- X wide = ceil (chars_on_line * char_width);
- X
- X x_user_offset = max (0, x_user_offset - p->left_marg);
- X y_user_offset = max (0, y_user_offset - p->top_marg );
- X
- X switch (max_frame)
- X {
- X case 1:
- X scale_x = (double) (p->x_size) / (double) wide;
- X scale_y = (double) (p->y_size) / (double) high;
- X x_left_offset = (int) ceil ((double) (p->left_marg + x_user_offset) / scale_x);
- X y_top_offset = (int) ceil ((double) (p->top_marg + y_user_offset) / scale_y);
- X dx_home[0] = 0;
- X dy_home[0] = 0;
- X p->height = ceil ((double) p->height / scale_y);
- X p->width = ceil ((double) p->width / scale_x);
- X p->bot_marg = ceil ((double) p->bot_marg / scale_y);
- X break;
- X
- X case 2:
- X scale_x = (double) (p->width - 2 * p->left_marg - 2 * p->right_marg)
- X / (double) (2 * wide);
- X scale_y = (double) (p->y_size) / (double) high;
- X
- X /* point offsets for margins account for physical "forbidden" area */
- X
- X x_left_offset = (int) ceil ((double) p->left_marg / scale_x);
- X y_top_offset = (int) ceil ((double) p->top_marg / scale_y);
- X
- X /* page origin translation vectors */
- X
- X p->height = ceil ((double) p->height / scale_y);
- X p->width = ceil ((double) p->width / (scale_x * 2.0));
- X p->bot_marg = ceil ((double) p->bot_marg / scale_y);
- X dx_home[0] = 0;
- X dy_home[0] = 0;
- X dx_home[1] = p->width;
- X dy_home[1] = 0;
- X break;
- X
- X case 4:
- X scale_x = (double) (p->width - 2 * p->left_marg - 2 * p->right_marg)
- X / (double) (2 * wide);
- X scale_y = (double) (p->height - 2 * p->top_marg - 2 * p->bot_marg)
- X / (double) (2 * high);
- X
- X /* point offsets for margins account for physical "forbidden" area */
- X
- X x_left_offset = (int) ceil ((double) p->left_marg / scale_x);
- X y_top_offset = (int) ceil ((double) p->top_marg / scale_y);
- X
- X /* page origin tranlsation vectors */
- X
- X p->height = ceil ((double) p->height / (scale_y * 2.0));
- X p->width = ceil ((double) p->width / (scale_x * 2.0));
- X p->bot_marg = ceil ((double) p->bot_marg / scale_y);
- X dx_home[0] = 0;
- X dy_home[0] = p->height;
- X dx_home[1] = 0;
- X dy_home[1] = -p->height;
- X dx_home[2] = p->width;
- X dy_home[2] = p->height;
- X dx_home[3] = 0;
- X dy_home[3] = -p->height;
- X break;
- X
- X default: ;
- X }
- X
- X if (max_frame > 1)
- X { x_left_offset += x_user_offset;
- X y_top_offset += y_user_offset;
- X }
- X
- X#ifdef DEBUG
- X printf ("%%!PS-Adobe-\n");
- X printf ("%% lines =%d/%d/%d chars = %d/%d\n", lines_total, set_line_count,set_total_count, chars_on_line, set_char_count);
- X printf ("%% height = %d / %d\n", p->height, high);
- X printf ("%% width = %d / %d\n", p->width, wide);
- X printf ("%% (lx,ly) = (%d,%d)\n", p->lx, p->ly);
- X printf ("%% (ux,uy) = (%d,%d)\n", p->ux, p->uy);
- X printf ("%% left_marg = %d\n", p->left_marg);
- X printf ("%% right_marg = %d\n", p->right_marg);
- X printf ("%% top_marg = %d\n", p->top_marg);
- X printf ("%% bot_marg = %d\n", p->bot_marg);
- X printf ("%% y_size = %d\n", p->y_size);
- X printf ("%% x_size = %d\n", p->x_size);
- X printf ("%% scale_x = %f scale_y = %f\n", scale_x, scale_y);
- X printf ("%% offset (lx,ty) = (%d,%d)\n", x_left_offset, y_top_offset);
- X printf ("%% home = %d %d %d %d\n",dy_home[0], dy_home[1], dy_home[2],dy_home[3]);
- X#endif
- X}
- X
- X
- X/****************************************************************************
- X* prologue () *
- X* generate the require postscript-conformant prologue *
- X****************************************************************************/
- X
- Xprologue ()
- X{ char *getlogin();
- X int i;
- X
- X if (book)
- X fprintf (output_fp, "%%Book file: psf-to-psd\n");
- X else
- X fprintf (output_fp, "%%!PS-Adobe-\n");
- X fprintf (output_fp, "%%%%Creator: %s\n", getlogin());
- X fprintf (output_fp, "%%%%CreationDate: %s\n", now);
- X fprintf (output_fp, "%%%%DocumentFonts: (atend)\n");
- X fprintf (output_fp, "%%%%Pages: (atend)\n");
- X fprintf (output_fp, "%%%%EndComments\n");
- X
- X#ifndef FONTINFO
- X /* The red book (pg 93) indicates that the FontInfo dictionary
- X "MAY" contain the /UnderlinePosition and /UnderlineThickness
- X This is the case for all Adobe fonts. External non-Adobe fonts may
- X not have these values.
- X
- X usage: (text to underline) <pointsize> showuline
- X where: <pointsize> is current text point size.
- X
- X eg: (text to underline) 12 showuline
- X */
- X fprintf (output_fp, "%s%s%s%s%s%s%s%s%s%s",
- X "/showuline {\n",
- X " /CurPointSize exch def\n",
- X " dup stringwidth pop\n",
- X " gsave\n",
- X " currentfont /FontInfo get dup\n",
- X " /UnderlinePosition get CurPointSize mul 1000 div 0 exch rmoveto exch 0 rlineto\n",
- X " /UnderlineThickness get CurPointSize mul 1000 div setlinewidth stroke\n",
- X " grestore\n",
- X " show\n",
- X "} def\n");
- X
- X#else
- X /* showunderline: without FontInfo: underline is 2 points below base
- X compliments of Anders Thulin
- X mcvax!helios!ath@uunet.uucp (Anders Thulin)
- X
- X usage: (text to underline) showunderline
- X */
- X fprintf (output_fp, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
- X "/showunderline {\n",
- X " /str exch def\n",
- X " /dy 0 def\n",
- X " currentpoint\n",
- X " str show\n",
- X " moveto\n",
- X " /dy -2 def\n",
- X " currentpoint\n",
- X " dy add\n",
- X " moveto\n",
- X " str stringwidth\n",
- X " rlineto \n",
- X " currentpoint\n",
- X " stroke\n",
- X " moveto\n",
- X " currentpoint\n",
- X " dy sub\n",
- X " moveto\n",
- X "} def\n");
- X#endif
- X
- X fprintf (output_fp, "%%%%EndProlog\n");
- X
- X if (set_paper_tray)
- X fprintf (output_fp, "%s\n", p->paper_tray);
- X
- X if (set_paper_bin)
- X fprintf (output_fp, "%s\n", slots[set_paper_bin - 1]);
- X}
- X
- X/****************************************************************************
- X* new_page () *
- X* Generate a new page. Send out required rotation,scale information *
- X* This is the "prologue" to a page (not the end of the previous) *
- X****************************************************************************/
- X
- Xnew_page ()
- X{
- X}
- X
- X
- X/****************************************************************************
- X* showpage () *
- X* Generate a real "showpage" if we have really finished generating a *
- X* physical page. If we are processing 2 or 4 up, then generate *
- X* coordinate "translates" if we really haven't finished all possible *
- X* page frames of the page. *
- X****************************************************************************/
- X
- Xshowpage (end_of_file)
- Xint end_of_file;
- X{
- X line_number = 0;
- X
- X if (++frame >= max_frame || end_of_file)
- X { if (bookwork == 0) /* psd will re-insert this */
- X fprintf (output_fp, "showpage pg restore\n");
- X frame = 0;
- X }
- X if (!end_of_file)
- X set_frame ();
- X}
- X
- X/****************************************************************************
- X* set_frame () *
- X* Select the next logical frame in two-up or four-up mode. If it is *
- X* the first frame of a physical page, the generate the %%Page *
- X****************************************************************************/
- X
- Xset_frame ()
- X{
- X if (frame == 0 || bookwork)
- X {
- X if (book) /* mark byte position of %%Page: for psd */
- X { pg_loc[npg_loc++] = ftell (output_fp);
- X }
- X fprintf (output_fp, "%%%%Page: ? %d\n", ++physical_page);
- X if (bookwork == 0) /* psd will re-insert these */
- X { fprintf (output_fp, "/pg save def\n");
- X if (landscape)
- X fprintf (output_fp, "90 rotate 0 %d translate\n", -real_width);
- X fprintf (output_fp, "%.5f %.5f scale\n", scale_x, scale_y);
- X }
- X findfont();
- X }
- X set_y_coord ();
- X
- X if (max_frame > 1 && bookwork == 0)
- X fprintf (output_fp, "%d %d translate\n", dx_home[frame], dy_home[frame]);
- X
- X if (frame == 0 && cross)
- X draw_cross();
- X
- X}
- X
- X
- X/****************************************************************************
- X* set_y_coord *
- X* position next line to the top of a logical page. *
- X*****************************************************************************/
- X
- Xset_y_coord ()
- X{
- X y_coord = p->height - y_top_offset - point_size;
- X}
- X
- X/****************************************************************************
- X* put_top *
- X* put a header line at the top of the page *
- X*****************************************************************************/
- X
- Xput_top ()
- X{
- X int save_attr, save_point;
- X
- X save_attr = print_attribute;
- X save_point = point_size;
- X print_attribute = BOLD;
- X point_size = 12;
- X
- X findfont();
- X moveto (0, y_coord, 1);
- X if (header == 1)
- X fprintf (output_fp, "(%-40s %3d %s)show\n", fname, page_number + 1, now);
- X else
- X fprintf (output_fp, "(%-40s %3d %s)show\n", header_text, page_number + 1, now);
- X y_coord -= point_size * 2;
- X x_coord = 0;
- X print_attribute = save_attr;
- X point_size = save_point;
- X findfont();
- X}
- X
- X/****************************************************************************
- X* process_file() *
- X* Read the file, look for escape sequences, put text in postscript form *
- X****************************************************************************/
- X
- Xprocess_file ()
- X{
- X int char_type, char_count, i, set_page, esc_type;
- X char *strchr ();
- X int previous_attribute;
- X int lcount = 0;
- X
- X set_page = 0;
- X while (fgets (line, LONG_STR, input_fp) != NULL)
- X {
- X if (lcount++ == 0)
- X { if ((i = tscan (line, "ta=")) >= 0)
- X { tab_size = atoi (line + i + 3);
- X }
- X /* we could also test here to see if the file is already
- X in postscript format and simply copy out the file
- X to stdout - however, we couldn't print postscript source.
- X By choice, detection of postscript is left to "psdetect"
- X in the back-end spooler.
- X
- X e.g. print postscript source with:
- X
- X psf thisfile.ps | lp
- X
- X will work even if psf is working in the print spooler.
- X */
- X }
- X if ((c = (unsigned char *) strchr (line, '\f')) != NULL)
- X {
- X if (c == line)
- X { line_number = 32000;
- X c = line + 1;
- X }
- X else
- X { *c = 0;
- X set_page = 1;
- X c = line;
- X }
- X }
- X else
- X c = line;
- X
- X if (line_number >= lines_on_page * 10)
- X { page_number++;
- X showpage (0);
- X line_number = 10;
- X if (header)
- X {
- X put_top();
- X line_number += 20;
- X }
- X }
- X else
- X line_number += 10;
- X
- X char_type = char_count = 0;
- X
- X /* for empty lines, don't generate a real moveto - but to call
- X to ensure that check for page overflow is done.
- X */
- X if (*c == '\n')
- X moveto (x_coord, y_coord, 0); /* don't gen moveto */
- X else
- X moveto (x_coord, y_coord, 1); /* do gen moveto */
- X
- X while (*c && *c != '\n')
- X {
- X if (char_type == 0)
- X fputc ('(', output_fp);
- X
- X switch ((int) *c)
- X {
- X case ESCAPE:
- X previous_attribute = print_attribute;
- X esc_type = *(++c);
- X if (escape_sequence (esc_type) == 0)
- X {
- X switch (esc_type)
- X {
- X case 'u':
- X SHOWU (output_fp, point_size);
- X break;
- X
- X
- X default:
- X if (char_type && (previous_attribute & UNDERLINE))
- X SHOWU (output_fp, point_size);
- X/*
- X else
- X if (c == line + 1 && (esc_type == '+' || esc_type == '-'))
- X ;
- X*/
- X else
- X fputs (")show\n", output_fp);
- X
- X if (esc_type == '+' || esc_type == '-')
- X
- X /* check for +/- 1/2 line feed */
- X
- X {
- X if (esc_type == '+')
- X y_coord -= point_size / 2;
- X else
- X y_coord += point_size / 2;
- X
- X moveto (x_coord, y_coord, 1);
- X char_type = -1;
- X c++;
- X if (*c != '\n')
- X fputc ('(', output_fp);
- X continue;
- X }
- X else
- X findfont (output_fp);
- X }
- X char_type = 0;
- X }
- X break;
- X
- X default:
- X if (*c == '\t')
- X {
- X fputc (' ', output_fp);
- X while (++char_count % tab_size)
- X fputc (' ', output_fp);
- X }
- X else
- X { if (strchr ("\r\b\\()", *c) != NULL)
- X fputc ('\\', output_fp);
- X fputc (*c, output_fp);
- X char_count++;
- X }
- X char_type = 1;
- X break;
- X }
- X c++;
- X }
- X if (char_type == 1)
- X { if (print_attribute & UNDERLINE)
- X SHOWU (output_fp, point_size);
- X else
- X fputs (")show\n", output_fp);
- X }
- X
- X y_coord -= point_size;
- X x_coord = 0;
- X if (set_page)
- X { line_number = 32000;
- X set_page = 0;
- X }
- X }
- X}
- X
- X/****************************************************************************
- X* escape_sequence () *
- X* If an escape sequence (esc,char) is found, mark which type of font *
- X****************************************************************************/
- X
- Xint escape_sequence (which)
- Xint which;
- X{ unsigned char s[10];
- X
- X switch (which)
- X {
- X case 'I':
- X print_attribute |= ITALICS;
- X break;
- X
- X case 'i':
- X print_attribute &= ~ITALICS;
- X break;
- X
- X case 'B':
- X print_attribute |= BOLD;
- X break;
- X
- X case 'b':
- X print_attribute &= ~BOLD;
- X break;
- X
- X case 'U':
- X print_attribute |= UNDERLINE;
- X break;
- X
- X case 'u':
- X print_attribute &= ~UNDERLINE;
- X break;
- X
- X case 'F':
- X s[0] = *(++c);
- X s[1] = '\0';
- X font_number = atoi (s);
- X if (font_number > (NFONTS / 4))
- X font_number = (NFONTS / 4) - 1;
- X break;
- X
- X case 'f':
- X font_number = default_font_number;
- X break;
- X
- X case 'P':
- X s[0] = *(++c);
- X s[1] = *(++c);
- X s[2] = '\0';
- X point_size = atoi (s);
- X break;
- X
- X case 'p':
- X point_size = default_point_size;
- X break;
- X
- X case '+':
- X case '-':
- X break;
- X
- X default:
- X return (-1);
- X ;
- X }
- X return (0);
- X}
- X
- X/****************************************************************************
- X* moveto () *
- X* Generate a postscript x y moveto statememt *
- X****************************************************************************/
- X
- Xmoveto (x, y, do_move)
- Xint x;
- Xint y;
- Xint do_move; /* 1 = gen moveto 0 = dont gen moveto */
- X{
- X /* ensure that the current line can fit on the page - including the
- X 1/4 line needed for the decenders
- X */
- X
- X if (line_number > lines_on_page * 10 || y < (p->bot_marg + point_size / 3))
- X {
- X showpage (0);
- X if (header)
- X {
- X put_top();
- X line_number += 20;
- X }
- X y = y_coord;
- X x = x_coord;
- X }
- X
- X if (do_move)
- X fprintf (output_fp, "%d %d moveto\n", x + x_left_offset, y);
- X}
- X
- X/****************************************************************************
- X* findfont () *
- X* generate a findfont statement *
- X****************************************************************************/
- X
- Xfindfont ()
- X{ int this;
- X
- X /* remove reference to UNDERLINE. Underline is not a font. */
- X
- X this = (font_number * 4) + (print_attribute & 0x03);
- X fonts_used[this] = 1;
- X fprintf (output_fp, "/%s findfont %d scalefont setfont\n", fonts[this], point_size);
- X}
- X
- X/****************************************************************************
- X* start_file () *
- X* Generate things that are appropriate for beginning of file processing *
- X****************************************************************************/
- X
- Xstart_file ()
- X{
- X line_number = 0;
- X print_attribute = 0;
- X page_number = 0;
- X frame = -1;
- X showpage (0);
- X if (header)
- X {
- X put_top();
- X line_number += 20;
- X }
- X}
- X
- X/****************************************************************************
- X* terminate_file () *
- X* Generate things that are appropriate for end of file processing *
- X****************************************************************************/
- X
- Xterminate_file ()
- X{
- X showpage (1);
- X}
- X
- X
- X/****************************************************************************
- X* terminate_printer () *
- X* Generate things that are appropriate wrap-up after all files printed *
- X* For double sided printing (book == 1), generate byte offset info. *
- X****************************************************************************/
- X
- Xterminate_printer ()
- X{ int i, used;
- X long psfptr;
- X
- X if (book)
- X { pg_loc[npg_loc++] = ftell (output_fp);
- X }
- X fprintf (output_fp, "%%%%Trailer\n");
- X for (used = i = 0; i < NFONTS; i++)
- X { if (fonts_used[i])
- X { used = 1;
- X break;
- X }
- X }
- X if (used)
- X { fprintf (output_fp, "%%%%DocumentFonts:");
- X for (i = 0; i < NFONTS; i ++)
- X { if (fonts_used[i])
- X fprintf (output_fp, " %s", fonts[i]);
- X }
- X fprintf (output_fp, "\n");
- X }
- X
- X fprintf (output_fp, "%%%%Pages: %d\n", physical_page);
- X
- X if (book) /* print statistics for psd */
- X {
- X psfptr = ftell (output_fp);
- X fprintf (output_fp, "%%PsfScale: %.5f %.5f scale\n", scale_x, scale_y);
- X fprintf (output_fp, "%%PsfMargin: %d %d %d %d %d\n",
- X max_frame, landscape, real_width, p->height, p->width);
- X for (i = 0; i < 4; i++)
- X fprintf (output_fp, "%%PsfHome: %d %d %d\n", i, dx_home[i], dy_home[i]);
- X for (i = 0; i < npg_loc-1; i++)
- X fprintf (output_fp, "%%PsfPg: %d %d\n", i, pg_loc[i]);
- X fprintf (output_fp, "%%PsfPg: 9999 %d\n", pg_loc[npg_loc-1]);
- X fprintf (output_fp, "%%PsfPtr: %d\n", psfptr);
- X }
- X fprintf (output_fp, "%c", 0x04); /* CTL/D = end job */
- X}
- X
- X/****************************************************************************
- X* draw_cross () *
- X* Draw horizontal and vertical separation lines between pages 4-up *
- X****************************************************************************/
- X
- Xdraw_cross ()
- X{ int p_w, p_h;
- X
- X if (max_frame == 4)
- X { p_w = p->width;
- X p_h = p->height;
- X fprintf (output_fp,"%d %d moveto\n", p_w, p_h);
- X fprintf (output_fp,"%d %d lineto\n", p_w, -p_h);
- X fprintf (output_fp,"%d %d moveto\n", 0, 0);
- X fprintf (output_fp,"%d %d lineto\n", p_w * 2, 0);
- X fprintf (output_fp,"%s\n", "stroke");
- X }
- X}
- X
- X/****************************************************************************
- X* output_book () *
- X* Send file "double sided print" mode. Used to make a "book". *
- X* Will pause the printer to ask for stack re-feed *
- X****************************************************************************/
- X
- Xoutput_book ()
- X{
- X#ifdef HOPPER
- X if (nslots > 1)
- X {
- X fflush (output_fp);
- X fclose (output_fp);
- X strcpy (line, BINDIR);
- X if (*line)
- X strcat (line, "/");
- X strcat (line, "psd -3 1psbook2.d34");
- X system (line);
- X unlink ("1psbook2.d34");
- X }
- X#endif
- X}
- X
- Xstatic char *usage_text[] =
- X{ "Usage: psf [-1|2|4] [-b n] [-c n] [-d] [-f n] [-g type ] [-h] [-H text]",
- X " [-i n] [-l n] [-m n] [-n] [-p n] [-t n] [-w] [-x] file...",
- X "where:",
- X " -1|2|4 print 1,2,4 up (default=1)",
- X " -b n paper bin n",
- X " -c n print columns",
- X " -d double sided",
- X " -f n font number (def=0:Courier)",
- X " -g type letter legal a4 b5",
- X " -h file name header",
- X " -H text text header",
- X " -i n indent left margin points",
- X " -l n print lines per page",
- X " -L n lines per page",
- X " -m n top margin points",
- X " -n portrait (narrow) format",
- X " -p n point size n",
- X " -t n tabs to n (default=8)",
- X " -w landscape (wide) format",
- X " -x draw cross (4-up page)",
- X " file.. name of files (or stdin)",
- X " output: stdout",
- X ""
- X} ;
- X
- Xusage ()
- X{ int i, many, n, ff;
- X
- X for (i = 0; i < 3; i++)
- X fprintf (stderr, "%s\n", usage_text[i]);
- X
- X many = sizeof (usage_text)/sizeof (char *) - 3;
- X
- X for (i = 0; i < many/2; i++)
- X fprintf (stderr, "%-38s %-38s\n", usage_text[i+3], usage_text[i+many/2+3]);
- X
- X fprintf (stderr,"Fonts selection with -f n (number or name)\n");
- X many = 0;
- X for (i = 0; i < NFONTS/4; i++)
- X { if (fonts_have[i*4])
- X { fprintf (stderr, "%2d %-18s", i, fonts[i*4]);
- X many++;
- X if ((ff = many % 3) == 0)
- X fprintf (stderr, "\n");
- X }
- X }
- X if (ff)
- X fprintf (stderr, "\n");
- X
- X fprintf (stderr, "Paper type/size selection with -g type\n");
- X many = 0;
- X for (i = 0; page_types[i].paper_name[0] != '\0'; i++)
- X { n = strlen (page_types[i].paper_name);
- X if (many + n > 75)
- X { many = 0;
- X fprintf (stderr,"\n");
- X ff = 0;
- X }
- X else ff = 1;
- X many += n + 3;
- X fprintf (stderr," %s", page_types[i].paper_name);
- X }
- X if (ff)
- X fprintf (stderr, "\n");
- X exit (0);
- X}
- X
- X/************************************************
- X* tscan (s,t) *
- X* char s[],t[]; *
- X* *
- X* Index function as defined in K&R *
- X* Look for string t in s *
- X* *
- X* return -1 if t does not exits in s *
- X* else return array position of first *
- X* character match *
- X************************************************/
- X
- X
- Xtscan (s, t)
- Xchar s[], t[];
- X{
- X int i, j, k;
- X for (i = 0; s[i] != '\0'; i++)
- X { for (j = i, k=0; t[k] != '\0' && s[j] == t[k]; j++, k++)
- X ;
- X if (t[k] == '\0')
- X return (i);
- X }
- X return (-1);
- X}
- X
- Xget_time (t)
- Xchar *t;
- X{
- X long n_time, time ();
- X char *x_time, *cc, *strchr();
- X
- X n_time = time (0); /* get time */
- X x_time = ctime (&n_time); /* convert ascii */
- X if ((cc = strchr (x_time, '\n')) != NULL)
- X *cc = '\0';
- X strcpy (t, x_time);
- X}
- X
- Xcompare (a,b)
- Xchar *a, *b;
- X{ int aa, bb;
- X
- X while (*a && *b)
- X { aa = *a++;
- X bb = *b++;
- X if (toupper (aa) != toupper (bb))
- X return (aa - bb);
- X }
- X return (0);
- X}
- X
- Xcomp (a,b)
- Xchar *a, *b;
- X{ int aa, bb;
- X
- X while (*a && *b)
- X { aa = *a++;
- X bb = *b++;
- X if (toupper (aa) != toupper (bb))
- X return (aa - bb);
- X }
- X if (*a == '\0' && *b == '\n')
- X return (0);
- X return (*a - *b);
- X}
- X
- Xtrim (s)
- Xchar *s;
- X{
- X while (*s)
- X { if (*s < ' ')
- X { *s = 0;
- X break;
- X }
- X s++;
- X }
- X}
- X
- Xbad_file()
- X{
- X fprintf (stderr, "Bad %s file\n", PDEF);
- X exit (1);
- X}
- END_OF_FILE
- if test 39736 -ne `wc -c <'psf.c'`; then
- echo shar: \"'psf.c'\" unpacked with wrong size!
- fi
- # end of 'psf.c'
- fi
- echo shar: End of archive 6 \(of 6\).
- cp /dev/null ark6isdone
- MISSING=""
- for I in 1 2 3 4 5 6 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 6 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-
-